//<<<+++OPENSOURCE
//<<<+++OPENSOURCE_LICENSE
/**
 * @addtogroup FPDFAPI
 * @{
 */

/**
 * @file
 * @brief PDF module manager and defines.
 */

//<<<+++OPENSOURCE_MUST_BEGIN
#ifndef _FPDF_MODULE_
#define _FPDF_MODULE_

#ifndef _FXCRT_EXTENSION_
	#include "../fxcrt/fx_ext.h"
#endif
//<<<+++OPENSOURCE_MUST_END

class CPDF_ModuleMgr;
class CPDF_PageModuleDef;
class CPDF_RenderModuleDef;
class CPDF_SecurityHandler;
class CCodec_ModuleMgr;
class CPDF_Dictionary;
class ICodec_JpegModule;
class ICodec_JpxModule;
class ICodec_FaxModule;
class ICodec_Jbig2Module;
class ICodec_IccModule;
class ICodec_FlateModule;

//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
class IPDF_GlyphProvider;
class IPDF_ExtSearchProvider;
class CPDF_DebugModuleDef;
//<<<+++OPENSOURCE_END

/**
 * @name Currently defined add-on modules.
 */
/*@{*/

/** @brief Eastern Asian Language Support. */
#define ADDIN_NAME_CJK			"Eastern Asian Language Support"
/** @brief JPEG2000 and JBIG2 Image Decoders. */
#define ADDIN_NAME_DECODER		"JPEG2000 and JBIG2 Image Decoders"

//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
/*@}*/

/**
 * @name Foxit PDF error code defines.
 */
/*@{*/

/** @brief Out of memory. */
#define FPDFERR_OUT_OF_MEMORY		1
/** @brief Missing feature. */
#define FPDFERR_MISSING_FEATURE		2

/*@}*/

/**
 * @brief PDF error report call-back function type.
 *
 * @param[in] code			The error code.
 * @param[in] msg			The error message.
 */
typedef void (*FPDF_ErrorReportFunc)(int code, FX_LPCSTR msg);
/**
 * @brief PDF security handler call-back function type.
 *
 * @param[in] name			The name of the security handler.
 */
typedef void (*FPDF_SecurityHandlerCallback)(FX_LPCSTR name);
//<<<+++OPENSOURCE_END
/**
 * @brief PDF module manager:
 * This is the root of all global data structure used in FPDFAPI.
 *
 * All FPDFAPI applications must create a module manager in order to call most features
 * provided in this library.
 * 
 * For each FPDFAPI module (either an executable, or a DLL), there can be only one 
 * module manager created. DLLs can share the module manager with main executable.
 */
class CPDF_ModuleMgr : public CFX_Object
{
public:
	/**
	 * Create and initialize a FPDFAPI module manager.
	 * The newly created module manager can be fetched by Get() function.
	 * Don't call this function more than once in one module.
	 */
	static void	Create();
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/**
	 * Use the module manager created in another module.
	 * This function is often used in DLL initialization, so the DLL can share the same
	 * module manager with the main executable (or another DLL).
	 */
	static void Use(CPDF_ModuleMgr* pMgr);
	//<<<+++OPENSOURCE_END

	/**
	 * Get the current module manager for this module.
	 * If a module manager is not set previously (either by Create or Use), this function
	 * will NOT automatically create a module manager.
	 */
	static CPDF_ModuleMgr*	Get();

	/**
	 * Destroy the current module manager.
	 * Normally, a module should call this function only if the module manager is created
	 * by this module.
	 * After the module manager destroyed, any features in this library
	 * involving some sort of global data can not be called any more.
	 */
	static void	Destroy();

	/**
	 * @name By default, only PDF file/object parsing is enabled in the module manager,
		to use more features, application must call corresponding initializer functions below.
		Or, call one of the convenience loaders according to the platform.
	 */
	/*@{*/

	/** Required */
	void		SetCodecModule(CCodec_ModuleMgr* pModule) { m_pCodecModule = pModule; }
	CCodec_ModuleMgr*		GetCodecModule() { return m_pCodecModule; }

	/** Required for parsing page contents/resources. */
	void		InitPageModule();
	/** Required for rendering PDF. By default, only FXGE driver enabled. */
	void		InitRenderModule();

	/*@}*/
    
	/**
	 * Explicitly set path for a module.
	 * This is often used by Linux apps because on Linux there is no default path.
	 * For Windows, the default path for all modules is the executable path. 
	 * If the module_name parameter is NULL, then all modules are expected to be installed in
	 * the specified folder, unless otherwise specified.
	 *
	 * @param[in] module_name		The input module name.
	 * @param[in] path				The input module path.
	 */
	void		SetModulePath(FX_LPCSTR module_name, FX_LPCSTR path);

	/**
	 * Get full path to a file in a module.
	 *
	 * @param[in] module_name		the input module name.
	 * @param[in] name				The module filename.
	 * @return The full file path for the module.
	 */
	CFX_ByteString GetModuleFilePath(FX_LPCSTR module_name, FX_LPCSTR name);

	/**
	 * Enable download-on-demand for add-on modules.
	 *
	 * @param[in] callback			The callback function triggered when need to download specified add-on module.
	 */
	void		SetDownloadCallback(FX_BOOL (*callback)(FX_LPCSTR module_name));

	/**
	 * Download a module. Requires support from download-on-demand callback.
	 *
	 * @param[in] module_name		The module name.
	 * @return Whether the module has been successfully downloaded.
	 */
	FX_BOOL		DownloadModule(FX_LPCSTR module_name);

	/**
	 * Notify a module becomes available.
	 *
	 * @param[in] module_name		The module name.
	 */
	void		NotifyModuleAvailable(FX_LPCSTR module_name);
    
    //<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/**
	 * Set the debug module.
	 *
	 * @param[in] pDebugModule		The input debug module.
	 */
	void		SetDebugModule(class CPDF_DebugModuleDef* pDebugModule);
    //<<<+++OPENSOURCE_END
	/**
	 * @name Getting all modules.
	 */
	/*@{*/

	/** Get the render module. */
	CPDF_RenderModuleDef*	GetRenderModule() const { return m_pRenderModule; }
	/** Get the page module. */
	CPDF_PageModuleDef*		GetPageModule() const { return m_pPageModule; }
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/** Get the debug module. */
	CPDF_DebugModuleDef*	GetDebugModule() const { return m_pDebugModule; }
	//<<<+++OPENSOURCE_END
	/*@}*/

	/**
	 * @name For embedded platforms, we provide the option to load embedded CMaps for each charset.
	 */
	/*@{*/
    //<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/** Use external data not embedded within the library, useful for some embedded system */
	static void				UseExternalData(FX_LPCBYTE pData, FX_DWORD size);
    //<<<+++OPENSOURCE_END
	/** Load CMaps for Adobe-GB1 character collection. */
	void					LoadEmbeddedGB1CMaps();
	/** Load CMaps for Adobe-CNS1 character collection. */
	void					LoadEmbeddedCNS1CMaps();
	/** Load CMaps for Adobe-Japan1 character collection. */
	void					LoadEmbeddedJapan1CMaps();
	/** Load CMaps for Adobe-Korea1 character collection. */
	void					LoadEmbeddedKorea1CMaps();

	/*@}*/

	ICodec_FaxModule*		GetFaxModule();
	ICodec_JpegModule*		GetJpegModule();
	ICodec_JpxModule*		GetJpxModule();
	ICodec_Jbig2Module*		GetJbig2Module();
	ICodec_IccModule*		GetIccModule();
	ICodec_FlateModule*		GetFlateModule();
    //<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/**
	 * Set the error reporting call-back function.
	 *
	 * @param[in] pErrorReportFunc		The new error reporting call-back function.
	 */
	void					SetErrorReportFunc(FPDF_ErrorReportFunc pErrorReportFunc);
	/**
	 * Report an error.
	 *
	 * @param[in] code			The error code.
	 * @param[in] msg			The error message.
	 */
	void					ReportError(int code, FX_LPCSTR msg);
    //<<<+++OPENSOURCE_END
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/** Get the memory manager. */
	FXMEM_FoxitMgr*			GetMemoryManager() { return m_pMemMgr; }

	/**
	 * Set a callback when unknown security handler name is found.
	 *
	 * @param[in] callback		The new callback function for unknown security handler.
	 */
	void					SetSecurityHandlerCallback(FPDF_SecurityHandlerCallback callback) { m_pSecurityHandlerCallback = callback; }
	/** Get the callback function for unknown security handler. */
	FPDF_SecurityHandlerCallback GetSecurityHandlerCallback() { return m_pSecurityHandlerCallback; }

	/** 
	 * Set the external search provider.
	 *
	 * @param[in] pProvider		The external search provider pointer.
	 */
	void					SetExternalSearchProvider(IPDF_ExtSearchProvider *pProvider);

	/** 
	 * Get the external search provider.
	 *
	 * @return The external search provider pointer.
	 */
	IPDF_ExtSearchProvider* GetExternalSearchProvider();
	//<<<+++OPENSOURCE_END
	/**
	 * Register or unregister a security handler.
	 *
	 * @param[in] name				The name of the security handler.
	 * @param[in] CreateHandler		The pointer of the create function of the security handler.
	 *								NULL for unregistering the handler. The application has to destroy the 
	 *								previously created handler.
	 *
	 * CreateHandler prototype:\n
	 *			CPDF_SecurityHandler *CreateHanlder(void *param);
	 * @param[in] param				The parameter for creating a security handler (for registering only).
	 */
	void					RegisterSecurityHandler(FX_LPCSTR name, CPDF_SecurityHandler* (*CreateHandler)(void* param), void* param);
	/**
	 * Create a security handler.
	 *
	 * @param[in] name				The name of the security handler. 
	 */
	CPDF_SecurityHandler*	CreateSecurityHandler(FX_LPCSTR name);

	/**
	 * Set private data.
	 * If the data points to an object that will belong to the attached object (which means
	 * when the attached object is destroyed, the private data should be destroyed too), then the caller
	 * must provide a callback for freeing the data.
	 * If the private data is just a number, or some external pointer, then the callback can be NULL.
	 *
	 * @note: this function will free any previously stored data for with same module ID.
	 *
	 * @param[in] module_id			The module id.
	 * @param[in] pData				The private data.
	 * @param[in] callback			The callback function for deallocating provided private data.				
	 */
	void					SetPrivateData(FX_LPVOID module_id, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback);

	/**
	 * Get previously stored private data. Returns NULL for not stored.
	 * This function works for private data set by SetPrivateData() or SetPrivateObj().
	 *
	 * @param[in] module_id			The module id.
	 * @return The private data identified by provided module id.
	 */
	FX_LPVOID				GetPrivateData(FX_LPVOID module_id);
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
#ifdef _FPDFAPI_MT_
	/** Get the lock of global data. */
	FX_CRITICAL_SECTION*	GetGlobalLock() { return &m_GlobalLock; }
#endif
//<<<+++OPENSOURCE_END
	/** The file buffer size. */
	int						m_FileBufSize;

protected:
	/** Default constructor. */
	CPDF_ModuleMgr();
	/** The destructor. */
	~CPDF_ModuleMgr();

	void					Initialize();

	/** Initialize modules. */
	void					InitModules();

	/**
	 * @name Global data structure for different modules. By default, all of the following pointers point to
	 * a null module which does nothing.
	 */
	/*@{*/

	/** External codec module */
	CCodec_ModuleMgr*		m_pCodecModule;
	/** The render module. */
	CPDF_RenderModuleDef*	m_pRenderModule;
	/** The page module. */
	CPDF_PageModuleDef*		m_pPageModule;
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/** The debug module. */
	CPDF_DebugModuleDef*	m_pDebugModule;
	/** External search provider. */
	IPDF_ExtSearchProvider*	m_pExtSearchProvider;
    //<<<+++OPENSOURCE_END
	/*@}*/

	/** The download callback function pointer. */
	FX_BOOL (*m_pDownloadCallback)(FX_LPCSTR module_name);
    //<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/** The error reporting callback function pointer. */
	FPDF_ErrorReportFunc	m_pErrorReportFunc;
	/** The callback function pointer for unknown security handler. */
	void (*m_pSecurityHandlerCallback)(FX_LPCSTR name);
    //<<<+++OPENSOURCE_END

	/** The default module path. */
	CFX_ByteString			m_DefaultModulePath;
	/** The module path list. mapping module names to CFX_ByteString. */
	CFX_CMapByteStringToPtr	m_ModulePathList;

	/** The security handler list. mapping security handler names to CPDF_SecurityHandler. */
	CFX_MapByteStringToPtr	m_SecurityHandlerMap;
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	/** The memory manager. */
	FXMEM_FoxitMgr*			m_pMemMgr;
	//<<<+++OPENSOURCE_END
	/** The private data in module. */
	CFX_PrivateData			m_privateData;
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
#ifdef _FPDFAPI_MT_
	/** The global critical section. */
	FX_CRITICAL_SECTION		m_GlobalLock;
#endif
//<<<+++OPENSOURCE_END
};

////////////////////////////////////////////////////////////////////////////////////////////////////
//
//	FPDFAPI modules
//
////////////////////////////////////////////////////////////////////////////////////////////////////

class CPDF_Document;
class CPDF_DocPageData;
class CPDF_FontGlobals;
class IPDF_FontMgr;
class IPDF_FontMapper;
class CPDF_ColorSpace;

/** @brief Page module. */
class CPDF_PageModuleDef : public CFX_Object
{
public:
	virtual ~CPDF_PageModuleDef() {}
	/**
	 * Create document data for page.
	 *
	 * @param[in] pDoc				The PDF document.
	 * @return The document page data.
	 */
	virtual CPDF_DocPageData*	CreateDocData(CPDF_Document* pDoc) { return NULL; }
	/** Release a document's data. */
	virtual void				ReleaseDoc(CPDF_Document*) {}
	virtual void				ClearDoc(CPDF_Document*){}

	/** Get font global data. */
	virtual CPDF_FontGlobals*	GetFontGlobals() { return NULL; }
	/** Clear stock font. */
	virtual void				ClearStockFont(CPDF_Document* pDoc) {}
	/** Notify CJK is available. */
	virtual void				NotifyCJKAvailable() {}
	/**
	 * Get stock color space.
	 *
	 * @param[in] family		The color space family.
	 * @return The stock color space.
	 */
	virtual CPDF_ColorSpace*	GetStockCS(int family) { return NULL; }
};

class CPDF_PageObjects;
class CFX_AffineMatrix;
class CPDF_RenderOptions;
class CPDF_Page;
class CPDF_DocRenderData;
class CPDF_PageRenderCache;
class CFX_BitmapDevice;
class CPDF_Stream;
class CFX_DIBSource;
class CPDF_RenderConfig;
class CPDF_Image;

/** @brief RENDER module, providing device independent page rendering. */
class CPDF_RenderModuleDef : public CFX_Object
{
public:
	virtual ~CPDF_RenderModuleDef() {}

	/**
	 * Create document data for render.
	 *
	 * @param[in] pDoc			The PDF document.
	 */
	virtual CPDF_DocRenderData*	CreateDocData(CPDF_Document* pDoc) { return NULL; }
	/** Destroy a document data for render. */
	virtual void	DestroyDocData(CPDF_DocRenderData*) {}
	virtual void	ClearDocData(CPDF_DocRenderData*) {}

	/** Get the document data for render. */
	virtual CPDF_DocRenderData* GetRenderData() { return NULL; }

	/**
	 * Create a page cache.
	 *
	 * @param[in] pPage			The input page.
	 * @return a page render cache.
	 */
	virtual CPDF_PageRenderCache*	CreatePageCache(CPDF_Page* pPage) { return NULL; }
	/** Destroy a page cache. */
	virtual void	DestroyPageCache(CPDF_PageRenderCache*) {}

	/** Notify Decoder is available. */
	virtual void	NotifyDecoderAvailable() {}

	/** Get the render configure. */
	virtual CPDF_RenderConfig* GetConfig() { return NULL; }
};
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
/** @brief Debug module. */
class CPDF_DebugModuleDef : public CFX_Object
{
public:
	/**
	 * Log a message.
	 *
	 * @param[in] msg			The msg to be logged.
	 */
	virtual void LogMsg(FX_LPCSTR msg) {}
};

/** 
 * @brief External search provider.
 *
 * For expand the search function. We support the external impliment the
 * search interface.
 */
class IPDF_ExtSearchProvider : public CFX_Object
{
public:
	/** 
	 * @param[in] pSrcText			The source text.
	 * @param[in] pSearchText		The text will be search.
	 * @param[in] bCaseSensitive	Whether the char code is case sensitive.
	 * @param[out] end_inddex		The first matching result's end index.
	 * @return The first matching result's start index for found out. -1 for not fount.
	 */
	virtual int			TextSearch (
							FX_LPCWSTR	pSrcText,  
							FX_LPCWSTR	pSearchText,
							FX_BOOL		bCaseSensitive,
							int&		end_index) = 0;

	/** 
	 * Release the current external provider.
	 */
	virtual void			Release() = 0;
};

class CPDF_SubstFont;
/**
 * @brief Glyph provider.
 *
 * For alternative platforms only:
 * Glyph provider: responsible for mapping font into one of more system font, 
 * getting glyph info, rendering glyph bitmap, and getting glyph path data.
 * NOTE: there is another IPDF_FontMapper interface in case the system can provide
 * Type1 or TrueType faces for substitution.
 */
class IPDF_GlyphProvider : public CFX_Object
{
public:
	/**
	 * Map font. For most mobile system with only one font, this function can simply return NULL.
	 * 
	 * @param[in] name				Original name.
	 * @param[in] bTrueType			TrueType or Type1.
	 * @param[in] flags				PDF font flags (see PDF Reference section 5.7.1).
	 * @param[in] font_weight		original font weight. 0 for not specified.
	 * @param[in] WindowPC			code page for charset (see Win32 GetACP()).
	 * @param[out] pSubstFont		It receives the substitute font data.
	 * @return The mapped font.
	 */
	virtual FX_LPVOID	MapFont(const CFX_ByteString& name,
								FX_BOOL bTrueType,
								FX_DWORD flags,
								int font_weight,
								int WindowPC,
								CPDF_SubstFont* pSubstFont
							)
							{ return NULL; }

	/**
	 * Return the glyph bounding box in PDF font units (1000 units per em).
	 *
	 * @param[in] font_handle		Returned by IPDF_GlyphProvider::MapFont.
	 * @param[in] unicode			Unicode for the character.	
	 * @param[in] pFont				The PDF font.
	 * @param[in] charcode			The original char code.
	 * @return The glyph bounding box.
	 */
	virtual FX_RECT		GetGlyphBBox(
							FX_LPVOID font_handle,
							FX_WCHAR unicode,
							class CPDF_Font* pFont,
							FX_DWORD charcode
							) = 0;

	/** @brief glyph bitmap type enumeration. */
	typedef enum {
		Mono,			/**< A monochrome bitmap, using 1 bit per pixel. */
		ByteMask,		/**< An 8-bit bitmap, generally used to represent anti-aliased glyph images. */
		ClearType		/**< An 8-bit ClearType bitmap (3x width). */
	} BitmapType;

	/**
	 * Get glyph bitmap. Implementation of this interface is required.
	 *
	 * @param[in] font_handle		Returned by MapFont.
	 * @param[in] unicode			Unicode for the character.
	 * @param[in] pFont				The PDF font.
	 * @param[in] charcode			The original char code.
	 * @param[in] pMatrix			The character matrix. Only a,b,c,d used.
	 * 								If the substitute flag indicates glyph transformation supported, then this can be
	 * 								any kind of matrix. Otherwise, only a,d have value, and a == d.
	 * @param[in,out] type			Bitmap type requested.
	 *								On return, this is the type actually offered by the provider.
	 * @param[out] left				Offset from the char origin to left side of the bitmap.
	 *								Negative is to the left, positive is to the right.
	 * @param[out] top				offset from the char origin to top side of the bitmap.
	 *								Negative is downward, positive is upward.
	 * @param[out] pixel_width		Width (in pixels) of the result bitmap.
	 * @param[out] pixel_height		Height (in pixels) of the result bitmap.
	 * @param[out] buffer			Result buffer. Must be allocated using FX_Alloc.
	 *								The buffer will be freed by FPDFAPI.
	 * @param[out] stride			Number of bytes per line in the result bitmap.
	 * @param[in] pdf_width			The width of the page.
	 * @return Return TRUE for success, FALSE for failure (or empty glyph).
	 */
	virtual FX_BOOL		GetGlyphBitmap(
							FX_LPVOID font_handle,
							FX_WCHAR unicode,
							class CPDF_Font* pFont,
							FX_DWORD charcode,
							const CFX_AffineMatrix* pMatrix,
							BitmapType& type,
							int& left,
							int& top,
							int& pixel_width,
							int& pixel_height,
							FX_LPBYTE& buffer,
							int& stride,
							int pdf_width
							) = 0;

	/**
	 * Get glyph path. Implementation of this interface is optional.
	 * The path data must be allocated using FX_NEW (it will be freed by FPDFAPI).
	 *
	 * @param[in] font_handle			Returned by MapFont.
	 * @param[in] unicode				Unicode for the character.
	 * @param[in] pFont					The PDF font.
	 * @param[in] charcode				The original char code.
	 * @return The glyph path data. Return NULL for failure (or empty glyph).
	 */
	virtual class CFX_PathData*	GetGlyphPath(
							FX_LPVOID font_handle,
							FX_WCHAR unicode,
							class CPDF_Font* pFont,
							FX_DWORD charcode
							) 
						{ return NULL; }
};

#ifdef _FPDF_DEBUG_
#define FPDF_DEBUG(a) CPDF_ModuleMgr::Get()->GetDebugModule()->LogMsg(a)
#else
/** @brief Foxit PDF debug output macro. */
#define FPDF_DEBUG(a)
#endif
//<<<+++OPENSOURCE_END

//<<<+++OPENSOURCE_MUST_BEGIN
#endif	// _FPDF_MODULE_
//<<<+++OPENSOURCE_MUST_END

/** @} */


